using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Watermelon;

public class UIController : MonoBehaviour
{
    // TODO: Add editor type filter attribute
    private Type defaultPage = typeof(UIGame);

    [SerializeField] UIPage[] pages;

    private static Type currentPage;

    private static Dictionary<Type, UIPage> pagesLink = new Dictionary<Type, UIPage>();

    private static bool isTablet;
    public static bool IsTablet => isTablet;

    private static Canvas mainCanvas;
    public static Canvas MainCanvas => mainCanvas;

    private static CanvasScaler canvasScaler;
    public static CanvasScaler CanvasScaler => canvasScaler;

    private static Camera mainCamera;

    public static OnPageOpenedCallback OnPageOpenedEvent;
    public static OnPageClosedCallback OnPageClosedEvent;

    public static UIGame GamePage => (UIGame)pagesLink[typeof(UIGame)];

    private void Awake()
    {
        mainCanvas = GetComponent<Canvas>();
        canvasScaler = GetComponent<CanvasScaler>();

        mainCamera = Camera.main;

        isTablet = GetTabletStage();

        CanvasScaler.matchWidthOrHeight = isTablet ? 1 : 0;

        pagesLink = new Dictionary<Type, UIPage>();
        for (int i = 0; i < pages.Length; i++)
        {
            pagesLink.Add(pages[i].GetType(), pages[i]);
        }
    }

    public void Initialise()
    {
        for (int i = 0; i < pages.Length; i++)
        {
            pages[i].Init();
            pages[i].Canvas.enabled = false;
        }

        ShowPage(defaultPage);
    }

    public static void ShowPage(Type pageType, bool immediately = false)
    {
        UIPage page = pagesLink[pageType];
        page.Canvas.enabled = true;

        if (!immediately)
        {
            page.Show();
        }
        else
        {
            page.ShowImmediately();
        }

        if (OnPageOpenedEvent != null)
            OnPageOpenedEvent.Invoke(pagesLink[pageType], pageType);

        currentPage = pageType;
    }

    public static void HidePage(Type pageType, bool immediately = false)
    {
        if (!immediately)
        {
            pagesLink[pageType].Hide();
        }
        else
        {
            pagesLink[pageType].HideImmediately();
        }

        if (OnPageClosedEvent != null)
            OnPageClosedEvent.Invoke(pagesLink[pageType], pageType);

        currentPage = typeof(UIGame);
    }

    public static T GetPage<T>() where T : UIPage
    {
        return pagesLink[typeof(T)] as T;
    }

    public static bool GetTabletStage()
    {
#if UNITY_IOS
            bool deviceIsIpad = UnityEngine.iOS.Device.generation.ToString().Contains("iPad");
            if (deviceIsIpad)
                return true;

            return false;
#else
        var aspectRatio = Mathf.Max(Screen.width, Screen.height) / (float)Mathf.Min(Screen.width, Screen.height);

        return (GetDeviceDiagonalSizeInInches() > 6.5f && aspectRatio < 1.5f);
#endif
    }

    public static Vector3 FixUIElementToWorld(Transform target, Vector3 offset)
    {
        Vector3 targPos = target.transform.position + offset;
        Vector3 camForward = mainCamera.transform.forward;

        float distInFrontOfCamera = Vector3.Dot(targPos - (mainCamera.transform.position + camForward), camForward);
        if (distInFrontOfCamera < 0f)
        {
            targPos -= camForward * distInFrontOfCamera;
        }

        return RectTransformUtility.WorldToScreenPoint(mainCamera, targPos);
    }

    public static float GetDeviceDiagonalSizeInInches()
    {
        float screenWidth = Screen.width / Screen.dpi;
        float screenHeight = Screen.height / Screen.dpi;
        float diagonalInches = Mathf.Sqrt(Mathf.Pow(screenWidth, 2) + Mathf.Pow(screenHeight, 2));

        return diagonalInches;
    }

    public delegate void OnPageOpenedCallback(UIPage page, Type pageType);
    public delegate void OnPageClosedCallback(UIPage page, Type pageType);
}
